import random
import datetime

from django.contrib import auth
from django.core import cache
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from ipware import get_client_ip

from .serializers import UserSerializer, LoginSerializer, \
    RegisterSerializer, ActivationSerializer, UpdateSerializer
from .utils import send_captcha_email


# Create your views here.
class CurrentUser(APIView):
    # 获取用户信息不会更新last_login的相关信息
    def get(self, request, format=None):
        serializer = UserSerializer(self.request.user)
        return Response(serializer.data)


class UserLogin(APIView):
    def post(self, request):
        # used for login
        user = get_object_or_404(auth.get_user_model().objects.all(),
                                 email=request.data.get('email'))
        ip_addr, _ = get_client_ip(request)
        serializer = LoginSerializer(user, data=request.data)
        if serializer.is_valid():
            user = serializer.save(login_ip=ip_addr)
            auth.login(request, user)
            return Response(UserSerializer(user).data)
        return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED)


class UserLogout(APIView):
    def delete(self, request):
        """
        used for logout
        """
        auth.logout(request)
        serializer = UserSerializer(request.user)
        return Response(serializer.data)  # return null response


class CaptchaSendView(APIView):
    @classmethod
    def generate_random_num(cls, length=6):
        random_num_list = random.sample(list(range(0, 10)), length)
        return ''.join(map(lambda x: str(x), random_num_list))

    @classmethod
    def get_cache_key(cls, email):
        return f'user_captcha_{email}'

    def post(self, request):
        """
        使用文件缓存系统，存储账号激活码
        """
        serializer = RegisterSerializer(data=request.data)
        if serializer.is_valid():
            user = serializer.save()  # update newest user info
            captcha = CaptchaSendView.generate_random_num()  # 生成随机的验证码
            cache_key = CaptchaSendView.get_cache_key(user.email)  # 验证码保存在缓存中
            current_timestamp = datetime.datetime.now().timestamp()
            cache_val = {'id': user.id,
                         'email': user.email,
                         'time': current_timestamp}
            cache_val = cache.cache.get_or_set(cache_key, cache_val, timeout=10 * 60)
            delta = abs(current_timestamp - cache_val.get('time'))
            if delta > 60 or delta < 1e-3:
                # 第一次发送或者距离上次发送时间超过60s，那么更新缓存中验证码和时间，并重新发送邮件
                cache_val['captcha'] = captcha
                cache_val['time'] = current_timestamp
                cache.cache.set(cache_key, cache_val)
                send_captcha_email(cache_val=cache_val, request=request)
                # no response data
                return Response(status=status.HTTP_201_CREATED)
            else:
                return Response({'detail': 'Interval of sending captcha too short'}, status=status.HTTP_400_BAD_REQUEST)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class UserActivationView(APIView):
    def post(self, request):
        serializer = ActivationSerializer(data=request.data)
        if serializer.is_valid():
            captcha = serializer.validated_data['captcha']
            email = serializer.validated_data['email']
            cache_key = CaptchaSendView.get_cache_key(email)
            cache_val = cache.cache.get(cache_key)
            if cache_val and cache_val.get('captcha') == captcha:
                serializer.save()
                return Response(status=status.HTTP_200_OK)
            if not cache_val:
                return Response({'captcha': '验证码已过期'}, status=status.HTTP_400_BAD_REQUEST)
            if cache_val.get('captcha') != captcha:
                return Response({'captcha': '验证码错误'}, status=status.HTTP_400_BAD_REQUEST)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class UserUpdateView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        serializer = UpdateSerializer(request.user, data=request.data)
        if serializer.is_valid():
            user = serializer.save()
            return Response(UserSerializer(user).data)  # 返回更新后的用户信息
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
